package com.g8.pethospitallearnbackend.service.impls;

import com.g8.pethospitallearnbackend.entity.Case;
import com.g8.pethospitallearnbackend.entity.Disease;
import com.g8.pethospitallearnbackend.entity.Learnprocess;
import com.g8.pethospitallearnbackend.exception.CustomException;
import com.g8.pethospitallearnbackend.mapper.CaseMapper;
import com.g8.pethospitallearnbackend.mapper.DiseaseMapper;
import com.g8.pethospitallearnbackend.mapper.LearnprocessMapper;
import com.g8.pethospitallearnbackend.service.CasefieldsService;
import com.g8.pethospitallearnbackend.service.LearnProcessService;
import com.g8.pethospitallearnbackend.utils.responseUtil.ResponseStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.g8.pethospitallearnbackend.utils.NewIdGenerateUtil.getNumber;

@Service
public class LearnProcessServiceImpl implements LearnProcessService {
    @Autowired
    private LearnprocessMapper learnprocessMapper;
    @Autowired
    private CaseMapper caseMapper;
    @Autowired
    private DiseaseMapper diseaseMapper;
    @Autowired
    private CasefieldsService casefieldsService;
    @Override
    public List<Learnprocess> getAllLearnProcesses() {
        return learnprocessMapper.selectAllProcessesByOrder();
    }

    @Override
    public List<Disease> getRelevantDiseasesFromCase(String caseId) {
        List<Disease> relevantDiseases=new ArrayList<>();
        //拿到病例信息
        Case specificCase=caseMapper.selectACaseById(caseId);
        if(specificCase==null){
            throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST,"该caseId在case表中不存在");
        }
        //该病例对应的病名数据，用|分割开,diseaseId的数组
        //!!!!!!!!!!!!!!!trim()只能去除开头和结尾的空格，中间不能去除
        String[] diseases=specificCase.getCaseDiseases().replace(" ","").split("\\|");
        for(String diseaseId:diseases){
            //根据diseaseId获取每个病的信息
            Disease disease=diseaseMapper.selectADiseaseById(diseaseId);
            if(disease==null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST,"该diseaseId在disease表中不存在");
            relevantDiseases.add(disease);
        }
        return relevantDiseases;
    }

    /**
     * 新增学习流程：
     * 1.要检验modules的list是否是casefields中存在的
     * 2.前端取消传递order，直接由后端生成一个maxorder+1，后面在修改接口中再修改顺序
     * 3.isVisible直接弃用全用1
     * @param learnprocess
     * @return
     */
    @Override
    public String addANewProcess(Learnprocess learnprocess) {
        //proName
        String proName=learnprocess.getProName();
        if(proName==null||proName.isBlank()) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"proName不能为空");
        //modules
        String modules=learnprocess.getModules().replace(" ","");
        if(modules==null||modules.isBlank()) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"modules不能为空");
        //验证proName是否已经出现过
        List<String> proNames=learnprocessMapper.selectAllProNames();
        if(proNames.contains(learnprocess.getProName())) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"proName已存在");
        String modulesStr=learnprocess.getModules().replace(" ","");

        //验证modules是否合法
        if(!validateModules(modulesStr)){
            throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"选择的病例模板不合法");
        }

        //生成新的id
        String newId='p'+getNumber(7);

        //生成order，是已有最大order+1
        int maxOrder=learnprocessMapper.selectMaxOrder();

        Learnprocess newProcess=new Learnprocess(
                newId,
                learnprocess.getProName(),
                maxOrder+1,
                (byte) 1,
                modulesStr
        );
        int code=learnprocessMapper.insert(newProcess);
        if(code!=1) throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR,"添加流程失败");


        return newId;
    }

    /**
     * 删除一个流程
     * 1.拿到要删除流程的order
     * 2.删除流程
     * 3.该流程order后面的往前迁移1个
     * @param proId
     * @return
     */
    @Override
    public String deleteAProcess(String proId) {
        //拿到要删除的order
        Integer deletedOrder= learnprocessMapper.selectOrderById(proId);
        if(deletedOrder==null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST,proId+"不存在");
        //删除操作
        int code=learnprocessMapper.deleteByPrimaryKey(proId);
        if(code!=1) throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR,"操作失败");
        //获取deletedOrder后面的learnprocess
        List<Learnprocess> toBeModified=learnprocessMapper.selectLargerThanOrder(deletedOrder);
        //修改toBeModified中的learnprocess的order
        for(Learnprocess process:toBeModified){
            Learnprocess modified=new Learnprocess(
                    process.getProId(),
                    process.getProName(),
                    process.getOrder()-1,
                    process.getIsVisible(),
                    process.getModules()
            );
            //更新order
            code=learnprocessMapper.updateByPrimaryKey(modified);
            if(code!=1) throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR,process.getProId()+"更新失败");
        }
        return proId;
    }

    /**
     * 修改一个流程
     * 1.修改proName直接改
     * 2.修改modules看这个字段是否是模板中的字段
     * 3.修改order整体order变化
     * @param proId
     * @param learnprocess
     * @return
     */
    @Override
    public String updateAProcess(String proId, Learnprocess learnprocess) {
        //proName
        String proName=learnprocess.getProName();
        if(proName==null||proName.isBlank()) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"proName不能为空");
        //modules
        String modules=learnprocess.getModules().replace(" ","");
        if(modules==null||modules.isBlank()) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"modules不能为空");

        //验证proName是否已经出现过
        List<String> proNames=learnprocessMapper.selectAllProNames();

        //bug修复：初心是想验证proName是否出现过，但是如果它修改的名字没有改变呢？
        String originalName=learnprocessMapper.selectProcessById(proId).getProName();
        String newName=learnprocess.getProName();
        if(!Objects.equals(originalName, newName) &&proNames.contains(newName)) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"proName已存在");
        //判断modules是否合法
        if(!validateModules(modules)){
            throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"修改后的模块不合法");
        }

        //处理order修改
        //判断order是否修改
        Integer originalOrder=learnprocessMapper.selectOrderById(proId);
        if(originalOrder==null) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"不存在"+proId);
        Integer newOrder=learnprocess.getOrder();
        if(newOrder==null) throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"newOrder不能为空");

        //修改order
        //判断要修改的order是否超过目前的最大order或者小于等于0都是不合法的
        Integer maxOrder= learnprocessMapper.selectMaxOrder();
        if(newOrder>maxOrder||newOrder<=0)
            throw new CustomException(ResponseStatusEnum.BAD_REQUEST,"要修改的order"+newOrder+"超出目前应有order范围");


        //其他order修改的情况
        if(originalOrder>newOrder){
            List<Learnprocess> modifiedProcesses=learnprocessMapper.selectBetweenOrder(newOrder,originalOrder);
            for(Learnprocess process:modifiedProcesses){
                Learnprocess modified=new Learnprocess(
                        process.getProId(),
                        process.getProName(),
                        process.getOrder()+1,
                        (byte) 1,
                        process.getModules()
                );
                int otherCode=learnprocessMapper.updateByPrimaryKey(modified);
                if(otherCode!=1)
                    throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR,"修改其他流程order失败"+process.getProId());
            }
        }
        else if(originalOrder<newOrder){
            List<Learnprocess> modifiedProcesses=learnprocessMapper.selectBetweenOrder(originalOrder+1,newOrder+1);
            for(Learnprocess process:modifiedProcesses){
                Learnprocess modified=new Learnprocess(
                        process.getProId(),
                        process.getProName(),
                        process.getOrder()-1,
                        (byte) 1,
                        process.getModules()
                );
                int otherCode=learnprocessMapper.updateByPrimaryKey(modified);
                if(otherCode!=1)
                    throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR,"修改其他流程order失败"+process.getProId());
            }
        }

        //反正都要改成新的,order顺序不改不用管，都要更新的
        Learnprocess newProcess=new Learnprocess(
                proId,
                proName,
                newOrder,
                (byte) 1,
                modules
        );
        int code=learnprocessMapper.updateByPrimaryKey(newProcess);
        if(code!=1)
            throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR,"修改失败");

        return proId;
    }

    public boolean validateModules(String modulesStr){
        //获取所有casefields英文enAttr
        List<String> enFields=casefieldsService.getEnFields();
        String[] modules=modulesStr.replace(" ","").split("&");

        //检验是否存在这个病例模块
        for(String module:modules){
            if(!enFields.contains(module)){
                return false;
            }
        }
        return true;
    }
}
